package cn.admin.remoting.impl;

import cn.admin.remoting.Client;
import cn.admin.remoting.ClientManager;
import cn.admin.remoting.ConnectCancelledException;
import cn.admin.remoting.RemotingException;
import cn.admin.remoting.locale.LogResources;
import org.apache.mina.common.ConnectFuture;
import org.apache.mina.common.RuntimeIOException;

public class ClientFutureImpl implements ClientManager.ClientFuture {

    private final String url;
    private final ConnectFuture minaFuture;

    ClientFutureImpl(String url,ConnectFuture minaFuture) {
        this.url = url;
        this.minaFuture = minaFuture;
    }

    @Override
    public String targetUrl() {
        return this.url;
    }

    @Override
    public void cancel() {
        String log = LogResources.getLog(LogResources.CONNECT_CANCEL,this.url);
        Exception ex = new ConnectCancelledException(log);
        this.minaFuture.setException(ex);
    }

    @Override
    public boolean isDone() {
        return this.minaFuture.isReady();
    }

    @Override
    public boolean isConnected() {
        if (!this.isDone()) {
            return false;
        } else {
            try {
                this.minaFuture.getSession();
                return true;
            } catch (RuntimeIOException e) {
                return false;
            }
        }
    }

    @Override
    public boolean isCancelled() {
        if (!this.isDone()) {
            return false;
        } else {
            try {
                this.minaFuture.getSession();
                return false;
            } catch (RuntimeIOException e) {
                return null != e.getCause() && e.getCause().getClass() == ConnectCancelledException.class;
            }
        }
    }

    @Override
    public Client get(long timeoutMs) throws RemotingException {
        if (timeoutMs < 0L) {
            this.minaFuture.join();
        } else if (timeoutMs > 0L) {
            this.minaFuture.join(timeoutMs);
        }

        if (!this.isDone()) {
            return null;
        } else {
            try {
                return DefaultClient.findBySession(this.minaFuture.getSession());
            } catch (RuntimeIOException e) {
                Throwable cause = e.getCause();
                if (null != cause && cause.getClass() == ConnectCancelledException.class) {
                    throw (ConnectCancelledException)cause;
                } else {
                    String log = LogResources.getLog(LogResources.CONNECT_FAIL,this.url);
                    throw new RemotingException(log,e.getCause());
                }
            }
        }
    }
}
